<template>
    <div :class="propJson.editFlag ? 'editUploadClass' : 'uploadClass'">
        <el-upload
            v-model:file-list="defaultFileList"
            :action="propJson.upLoadUrl"
            :limit="propJson.isUpLoadLimit ? propJson.upLoadLimit : 0"
            :with-credentials="true"
            :multiple="propJson.isMultiple"
            :show-file-list="propJson.isShowFileList"
            :drag="propJson.isDraggable"
            :on-exceed="handleExceed"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :on-success="handleSuccess"
            :on-error="handleError"
            :on-progress="handleProgress"
            :before-upload="handleBeforeUpload"
            :list-type="propJson.listType"
            :auto-upload="true"
            :disabled="propJson.isDisabled"
            :data="execUploadData"
            :class="propJson.uploadSelectType === 'icon' && !propJson.isDraggable ? 'avatar-uploader' : ''"
            :info="getFileListInfo"
        >
            <el-button type="primary" v-if="propJson.uploadSelectType === 'button'">{{propJson.buttonName}}</el-button>
            <el-icon class="el-icon--upload" v-if="propJson.uploadSelectType === 'icon' && propJson.isDisable">
                <component is="CloudUploadOutlined" />
            </el-icon>
            <div class="el-upload__text" v-if="propJson.uploadSelectType === 'icon' && propJson.isDisable">
                {{propJson.buttonName}}
            </div>
            <el-icon :style="execIconStyle" v-if="propJson.uploadSelectType === 'icon'">
                <component is="PlusOutlined" />
            </el-icon>
            <template #tip v-if="propJson.isShowTips">
                <div style="text-align: center">
                    <span v-for="item in showTips" :key="item">
                        {{item}} <br />
                    </span>
                </div>
            </template>
        </el-upload>

        <el-dialog v-model="dialogVisible" style="width: 90%; height: auto">
            <img :src="dialogImageUrl" alt="Preview Image" style="object-fit: contain; width: 100%; height: auto"/>
        </el-dialog>
    </div>
</template>

<script name="FileUploadComponent" setup lang="ts">
import {ElNotification} from "element-plus";
import {doThirdServiceValue, getBuildParam} from "@/utils/lowcode/thirdService";
import {computed, defineProps, ref} from "vue";
import {getCommonParamInfo, getCommonParamObj} from "@/utils/commonParamUtil";
import jsonpath from "jsonpath";
import {doThirdExecInfo} from "@/request/lowcode";

let props = defineProps(['propJson', 'commonParam']);

let propJson = computed(() => {return props['propJson']})
let commonParam = computed(() => {return props['commonParam']})

let dialogVisible = ref(false);
let dialogImageUrl = ref("");
let defaultFileList = ref([]);

let execIconStyle = computed(() => {
    let iconStyle = "";
    iconStyle += "color: #8c939d;";
    iconStyle += "text-align: center;";
    iconStyle += "font-size: " + propJson.value.iconFontSize + ";";
    iconStyle += "height: " + propJson.value.iconFontHeight + ";";
    return iconStyle;
})

let showTips = computed(() => {
    let resTips = [];
    if (!propJson.value.isShowTips) {
        return resTips;
    }
    if (propJson.value.isLimitFileSize) {
        resTips.push("文件大小限制为" + propJson.value.limitFileSize);
    }
    if (propJson.value.tipInfo) {
        resTips.push(propJson.value.tipInfo)
    }
    return resTips;
})

let execUploadData = computed(() => {
    let actionInfo = {
        apiParamList: propJson.value.uploadDataValue
    }
    return getBuildParam(actionInfo, commonParam.value)
})

let getFileListInfo = computed(() => {
    getFileList();
})

function execThen(resValue) {
    if (resValue) {
        defaultFileList.value = resValue;
    } else {
        defaultFileList.value = [];
    }
}

async function getFileList() {
    if (propJson.value.isShowFileList) {
        if (propJson.value.editFlag) {
            return defaultFileList.value = [];
        }
        await doThirdServiceValue(propJson.value.defaultFileListInfo, commonParam.value, execThen, () => {}, null)
    } else {
        defaultFileList.value = [];
    }
}

function handleExceed() {
    // 上传失败
    ElNotification({
        title: 'Error',
        message: "上传超出限制",
        type: 'error',
    });
}

function handlePreview(file) {
    if (propJson.value.listType === 'picture-card') {
        dialogImageUrl.value = file.url;
        dialogVisible.value = true;
    }
}

function handleRemove(file, files) {

}

async function handleSuccess(response, file, files) {
    if (response.code === "200" || response.code === 200) {
        // 上传成功
        ElNotification({
            title: 'Success',
            message: "成功",
            type: 'success',
        });
        let realResponse = response;
        // 是否需要后置三方服务
        if (propJson.value.isAddAfterThirdExec) {
            // 构建三方服务入参
            let execParamInfo = []
            let execParamInfoJson = propJson.value.afterExecParamJson
            for (let index = 0; index < execParamInfoJson.length; index++) {
                let info = execParamInfoJson[index]
                let tempParam = {
                    name: info.name,
                    type: info.type,
                    isArray: info.isArray,
                    value: ""
                }
                if (info["execParamInfo"]["selectType"] === 'custom') {
                    if (info["execParamInfo"]["customContent"].startsWith("$")) {
                        let jsonRes = jsonpath.query(response, info["execParamInfo"]["customContent"]);
                        tempParam.value = JSON.stringify(jsonRes)
                    } else {
                        tempParam.value = info["execParamInfo"]["customContent"]
                    }
                } else {
                    // 获取参数内容
                    let resParamInfo = getCommonParamInfo(commonParam.value, info["execParamInfo"]["variableName"])
                    if (typeof resParamInfo !== "string") {
                        tempParam.value = JSON.stringify(resParamInfo)
                    } else {
                        tempParam.value = resParamInfo
                    }
                }
                execParamInfo.push(tempParam)
            }
            // 添加额外响应入参
            execParamInfo.push({
                isArray: false,
                name: "responseData",
                type: "string",
                value: JSON.stringify(response)
            })
            // 执行三方服务
            let resParamInfo = ""
            let doThirdExecParam = {
                code: propJson.value.afterThirdExecCode,
                execParam: execParamInfo
            }
            await doThirdExecInfo(doThirdExecParam).then(res => {
                let data = res.data;
                try {
                    resParamInfo = JSON.parse(data)
                } catch (err) {
                    console.log("json parse error, use default value!!")
                    resParamInfo = data
                }
            })
            realResponse = resParamInfo;
        }
        // 响应参数映射
        for (let i = 0; i < propJson.value.uploadResponseParamList.length; i++) {
            let responseParam = propJson.value.uploadResponseParamList[i]
            // 从返回的结果中解析值
            let jsonPathInfo = responseParam.variableValue
            let commonParamObj = getCommonParamObj(commonParam.value, responseParam["variableName"])
            let resValue = ""
            if (commonParamObj["variableType"] === "Array") {
                resValue = jsonpath.query(realResponse, jsonPathInfo)
            } else if (commonParamObj["variableType"] === "String") {
                let temp = jsonpath.query(realResponse, jsonPathInfo)[0]
                if (typeof temp === "string") {
                    resValue = temp;
                } else {
                    resValue = JSON.stringify(temp);
                }
            } else {
                resValue = jsonpath.query(realResponse, jsonPathInfo)[0]
            }
            commonParamObj.variableValue = resValue
        }
    } else {
        // 上传失败
        ElNotification({
            title: 'Error',
            message: response.errorCode + ":" + response.message,
            type: 'error',
        });
    }
}

function handleError(error, file, files) {
    // 上传失败
    ElNotification({
        title: 'Error',
        message: error,
        type: 'error',
    });
}

function handleProgress() {

}

function handleBeforeUpload(file) {
    // 判断文件的大小是否超出限制
    if (propJson.value.isLimitFileSize) {
        if (!propJson.value.limitFileSize) {
            // 上传失败
            ElNotification({
                title: 'Error',
                message: "文件大小超出限制",
                type: 'error',
            });
            return false;
        }
        let fileSize = propJson.value.limitFileSize;
        let sizeRes = 0;
        // 根据后缀进行大小计算
        let sizeBefore = fileSize.substring(0, fileSize.length - 2);
        let sizeAfter = fileSize.substring(fileSize.length - 2, fileSize.length);
        if (sizeAfter === "KB" || sizeAfter === "kb") {
            sizeRes = sizeBefore * 1024;
        } else if (sizeAfter === "MB" || sizeAfter === "mb") {
            sizeRes = sizeBefore * 1024 * 1024;
        } else if (sizeAfter === "GB" || sizeAfter === "gb") {
            sizeRes = sizeBefore * 1024 * 1024 * 1024;
        }
        if (file.size > sizeRes) {
            // 上传失败
            ElNotification({
                title: 'Error',
                message: "文件大小超出限制",
                type: 'error',
            });
            return false;
        }
    }
    return true;
}
</script>

<style scoped lang="less">
.avatar-uploader {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
    width: 100%;
}


/deep/ .el-upload {
    width: 100% !important;
}

.avatar-uploader:hover {
    border-color: var(--el-color-primary);
}

.uploadClass {
    padding: 10px;
}

.editUploadClass {
    padding: 10px 60px;
}

/deep/ .el-upload-list--picture-card {
    width: 100% !important;
}
</style>